<template>
  <div>
    <x-form :ref="setItemRef" v-model:model="getProps.params" :rules="rules" label-placement="top" label-width="120">
      <n-form-item :label="title" path="default">
        <template v-if="getProps.params.element_type === 'ELEMENT_TYPE_ENUM'">
          <div class="flex">
            <n-select
              v-model:value="getProps.params.default"
              class="flex-item"
              :placeholder="title"
              :multiple="multiple"
              :multiple-limit="limit"
              :options="enumeration"
              label-field="description"
              value-field="value"
              filterable
              clearable
              @update:value="onChangeSelect"
            >
              <template v-if="getProps.isChannels" #action>
                <x-button type="primary" :text="true" @click="onUpdateChannel">视频号授权</x-button>
              </template>
            </n-select>
            <x-button v-if="getProps.isUpdate" type="primary" plain style="margin-left: 10px" @click="onUpdateActions"
              >刷新</x-button
            >
          </div>
        </template>
        <!--落地页选择-->
        <template v-else-if="getProps.params.element_type === 'ELEMENT_TYPE_URL'">
          <FAdPage v-model:pid="getProps.params.default" :required="getProps.required" is-url="is-url" />
        </template>
        <template v-else>
          <div class="flex" style="flex: 1; position: relative">
            <div class="textarea-input flex-item" style="position: relative">
              <n-input
                ref="inputRef"
                v-model:value="getProps.params.default"
                :type="isTextarea ? 'textarea' : 'text'"
                :placeholder="title"
              >
              </n-input>
              <div
                class="flex"
                style="
                  align-items: center;
                  padding: 10px 0;
                  justify-content: flex-end;
                  position: absolute;
                  right: 0;
                  bottom: -35px;
                "
              >
                <x-button v-if="getProps.params.copy_tool === '文案助手'" :text="true" @click="onShowTextTools"
                  >文案助手</x-button
                >
                <n-divider v-if="getProps.params.copy_tool === '文案助手'" vertical />
                <n-popover v-if="getProps.expression" class="m-popper-emoji">
                  <template #trigger>
                    <x-button :text="true">表情</x-button>
                  </template>
                  <ul>
                    <template v-for="(item, index) in emojiList" :key="index">
                      <li @click="insertEmoji(item, isTextarea ? 'textarea' : 'input')">
                        <n-image :src="emojiPic(item)" preview-disabled />
                      </li>
                    </template>
                  </ul>
                </n-popover>
                <n-divider v-if="getProps.expression" vertical />
                <div>
                  <span class="count-inner">{{ count }}/{{ entity.max_length }}</span>
                </div>
              </div>
            </div>
          </div>
        </template>
      </n-form-item>
    </x-form>
    <n-modal v-model:show="dialogVisible" title="文案助手" preset="card" :style="{ width: '500px' }">
      <n-select
        key="text"
        v-model:value="changeText"
        :loading="dialogLoading"
        :options="textToolsList"
        label-field="text"
        value-field="text"
        placeholder="下拉选择文案，输入关键字过滤"
        filterable
      />
      <template #footer class="dialog-footer">
        <x-button @click="dialogVisible = false">取 消</x-button>
        <x-button type="primary" @click="onChangeText">确 定</x-button>
      </template>
    </n-modal>
  </div>
</template>

<script setup lang="ts">
  import { XLayoutMain, XDataTable, XButton, XForm } from '@/components'
  import { useRoute, useRouter } from 'vue-router'
  import { computed, h, onMounted, reactive, ref, VNode, watch } from 'vue'
  import { EMOJI_UNICODES } from '@/utils/emoji'
  const message = useMessage()
  import {
    NCard,
    NDivider,
    NModal,
    NInput,
    NImage,
    NPopover,
    useMessage,
    NSelect,
    NIcon,
    NText,
    NFormItem,
    NRadioGroup,
    NRadio
  } from 'naive-ui'
  import { useStore } from '@/store'
  import FAdPage from '@/views/advertising/ads/create/components/step7/FAdPage.vue'

  const router = useRouter()
  const route = useRoute()
  const store = useStore()
  const emit = defineEmits(['change', 'upload'])
  const props = defineProps({
    params: {
      type: Object,
      default: () => ({})
    },
    // 是否只展示10个字符长度
    isLengthController: {
      type: Boolean,
      default: false
    },
    // 是否展示动态词包
    dynamic: {
      type: Boolean,
      default: true
    },
    // 是否支持换行
    textarea: {
      type: Boolean,
      default: false
    },
    // 必填项
    required: {
      type: Boolean,
      default: false
    },
    // 表情
    expression: {
      type: Boolean,
      default: false
    },
    // 投放页面类型，来控制行动按钮是否只展示小程序
    landingPageType: {
      type: String,
      default: ''
    },
    // 更新列表
    isUpdate: {
      type: Boolean,
      default: false
    },
    // 视频号
    isChannels: {
      type: Boolean,
      default: false
    }
  })
  const getProps = reactive(props)
  const accountCode = computed(() => {
    return store.state.intelligent.data.accountCode
  })
  const advertiser = computed(() => {
    return store.state.intelligent.advertiser
  })
  const isEdit = computed(() => {
    return !!store.state.intelligent.data.id
  })
  const base = computed(() => {
    return store.state.intelligent.data.base
  })
  const isTextarea = computed(() => {
    return getProps.textarea
  })
  const title = computed(() => {
    return typeof getProps.params.description === 'string'
      ? getProps.params.description.split('，')?.length > 0
        ? getProps.params.description.split('，')[0]
        : ''
      : '文案'
  })
  const enumeration = computed(() => {
    if (getProps.params.element_type === 'ELEMENT_TYPE_ENUM') {
      const list = getProps.params.enum_property ? getProps.params.enum_property.enumeration || [] : []
      // 朋友圈广告  链接名称类型
      if (getProps.params.name === 'link_name_type') {
        // 马到商家，只能选择进入小程序，但如果投放页面类型选择的是小程序，就都可以选
        // PAGE_TYPE_MOMENTS_SIMPLE_NATIVE_WECHAT - 简版原生页
        // PAGE_TYPE_CANVAS_WECHAT - 原生推广页
        // PAGE_TYPE_MINI_PROGRAM_WECHAT - 微信小程序
        if (['PAGE_TYPE_MINI_PROGRAM_WECHAT'].includes(getProps.landingPageType)) {
          // 选择小程序时，去逛逛暂时不支持，过滤掉
          return list.filter((item) => item.value !== 'GO_SHOPPING')
        } else if (
          base.value.pageType === 2 &&
          ['PAGE_TYPE_MOMENTS_SIMPLE_NATIVE_WECHAT'].includes(getProps.landingPageType)
        ) {
          return list.filter((item) => item.value === 'ENTER_MINI_PROGRAM')
        } else if (base.value.pageType === 1) {
          // 枫页
          return list.filter((item) => item.value !== 'ENTER_MINI_PROGRAM')
        } else {
          return list
        }
      } else {
        return list
      }
    } else {
      return []
    }
  })
  const entity = computed(() => {
    return initEntity()
  })
  const multiple = computed(() => {
    return getProps.params.field_type === 'FIELD_TYPE_STRING_ARRAY'
  })
  const limit = computed(() => {
    return multiple.value ? getProps.params.array_property.max_number : 0
  })
  const count = computed(() => {
    if (!getProps.params.default) return 0
    const len = 0
    let t = 0
    const key = getProps.params.default.match(/\{\{(.+?)\}\}/g)
    const emoji = getProps.params.default.match(/\[(.+?)\]/g)
    let content = getProps.params.default.replace(/\{\{(.+?)\}\}/g, '')
    // 支持表情
    if (getProps.expression) {
      content = content.replace(/\[(.+?)\]/g, '')
    }
    for (let a = content.length, n = -1, r = 0; r < a; r++) {
      n = content.charCodeAt(r)
      t += n >= 0 && n <= 128 ? 0.5 : 1
    }
    // 计算动态词包长度
    if (key && key.length) {
      key.forEach((item) => {
        switch (item) {
          case '{{city}}':
            t += 4
            break
          case '{{gender}}':
            t += 2
            break
          case '{{day}}':
            t += 6
            break
          case '{{week}}':
            t += 3
            break
        }
      })
    }
    if (getProps.expression && emoji && emoji.length) {
      t += emoji.length
    }
    return len + Math.ceil(t)
  })
  const rules = ref({
    default: []
  })
  const inputRef = ref()
  const dialogVisible = ref(false)
  const dialogLoading = ref(false)
  const buttonTextType = ref('默认文案')
  const checked = ref(false)
  const changeText = ref()
  const textToolsList = ref([])
  const emojiList = EMOJI_UNICODES

  const itemRefs = {}
  const setItemRef = (el: any) => {
    if (el) {
      const key = getProps.params.name
      itemRefs[key] = el
    }
  }
  onMounted(() => {
    initRules()
    if (getProps.params.element_type === 'ELEMENT_TYPE_ENUM') {
      onUpdateActions()
      onChangeSelect()
    }
  })
  watch(
    () => getProps.isLengthController,
    (val) => {
      if (val) {
        initEntity()
      }
    },
    {
      immediate: true,
      deep: true
    }
  )
  // 初始化校验规则
  function initRules() {
    // 自定义长度校验
    const validateLength = (rule, value, callback) => {
      const msg = `长度在 ${entity.value.min_length || 1} 到 ${entity.value.max_length} 个字符`
      if (count.value >= 1 && count.value < entity.value.min_length) {
        callback(msg)
      } else if (count.value > entity.value.max_length) {
        callback(msg)
      } else {
        callback()
      }
    }
    // 必填、可选
    if (getProps.required || getProps.params.required) {
      rules.value.default.push({
        type: 'string',
        required: getProps.required || getProps.params.required,
        message: `${title.value}不能为空`,
        trigger: ['blur', 'change']
      })
    }
    if (!entity.value) return false
    // 最小、最长度
    if (entity.value.min_length || entity.value.max_length) {
      rules.value.default.push({
        type: 'string',
        validator: validateLength,
        trigger: ['blur', 'change']
      })
    }
    // 特殊字符正则校验
    if (entity.value.text_pattern) {
      const pattern = isTextarea.value
        ? entity.value.text_pattern.replace('\\x08\\x09\\x0A\\x0D', '')
        : entity.value.text_pattern // 支持\r\n
      rules.value.default.push({
        type: 'string',
        pattern,
        message: `${title.value.replace(/（可选）|\(可选\)/g, '')}，不能含有特殊字符`,
        trigger: ['blur', 'change']
      })
    }
    // url正则校验
    if (entity.value.url_pattern) {
      rules.value.default.push({
        type: 'string',
        pattern: entity.value.url_pattern,
        message: `请选择正确的${title.value}`,
        trigger: ['blur', 'change']
      })
    }
  }
  // 复选框切换
  function onChangeSelect() {
    const find = enumeration.value.find((item) => item.value === getProps.params.default)
    emit('change', getProps.params.default, find)
  }
  function emojiPic(row) {
    return `https://wxa.wxs.qq.com/wxad-design/emojis/${row.img}.png`
  }
  function insertEmoji(val, type = 'textarea') {
    const input = inputRef.value
    if (input) {
      // 原生属性selectionStart  selectionEnd无法获取到
      const elRef = input.textareaElRef || input.inputElRef
      const start = elRef.selectionStart
      const end = elRef.selectionEnd
      // const start = input.handleCompositionStart
      // const end = input.handleCompositionEnd
      const text = getProps.params.default || ''
      const len = text.match(/\[(.+?)\]/gi)
      const max = type === 'textarea' ? 4 : 1
      if (len && len.length >= max) {
        message.warning(`仅支持添加${max}个表情`)
      } else {
        getProps.params.default = text.substr(0, start) + val.text + text.substr(end)
      }
    }
  }
  function initEntity() {
    if (getProps.isLengthController) {
      if (getProps.params.restriction) {
        if (getProps.params.element_type === 'ELEMENT_TYPE_URL') {
          const restriction = JSON.parse(JSON.stringify(getProps.params.restriction)) || null
          if (restriction.url_restriction.url_pattern) restriction.url_restriction.url_pattern.max_length = 10
          return restriction.url_restriction.url_pattern || false
        } else {
          const restriction = JSON.parse(JSON.stringify(getProps.params.restriction)) || null
          if (restriction.text_restriction) restriction.text_restriction.max_length = 10
          return restriction.text_restriction || false
        }
      } else {
        return false
      }
    } else {
      return getProps.params.restriction
        ? getProps.params.element_type === 'ELEMENT_TYPE_URL'
          ? getProps.params.restriction.url_restriction.url_pattern
          : getProps.params.restriction.text_restriction
        : false
    }
  }
  // 校验
  function validate() {
    return new Promise((resolve, reject) => {
      itemRefs[getProps.params.name]?.validate((errors) => {
        if (!errors) {
          resolve({
            [getProps.params.name]: getProps.params.default
          })
        } else {
          message.warning(`请正确填写${title.value}`)
          resolve(false)
        }
      })
    })
  }
  function onShowTextTools() {
    changeText.value = null
    dialogVisible.value = true
    dialogLoading.value = true
    store
      .dispatch('intelligent/getAdsText', {
        accountCode: accountCode.value,
        length: entity.value.max_length
      })
      .then((res) => {
        textToolsList.value = res.data || []
        dialogLoading.value = false
      })
      .catch(() => {
        dialogLoading.value = false
      })
  }
  // 选择当前文案助手数据
  function onChangeText() {
    dialogVisible.value = false
    if (changeText.value) {
      getProps.params.default = changeText.value
    }
  }
  // 更新动作
  function onUpdateActions() {
    emit('upload')
  }
  function handleBlur() {
    const value = getProps.params.default || ''
    // 移除首尾空格换行
    getProps.params.default = value.replace(/^\s{1,}/, '').replace(/\s{1,}$/g, '')
  }

  function onUpdateChannel() {
    window.open(`https://ad.qq.com/atlas/${accountCode.value}/tool/wechat-channel`)
  }

  defineExpose({
    validate
  })
</script>

<style scoped lang="scss">
  .textarea-input {
    position: relative;
    .is-textarea {
      .count-inner {
        font-size: 12px;
        color: #a4a4a4;
        line-height: 1;
        padding: 0 5px;
      }
    }
  }
  .m-popper-emoji {
    ul,
    li {
      margin: 0;
      padding: 0;
      list-style: none;
    }
    ul {
      display: flex;
      flex-wrap: wrap;
      width: 260px;
    }
    li {
      width: 26px;
      height: 26px;
      overflow: hidden;
      padding: 2px;
      cursor: pointer;
      &:hover {
        background-color: #ddd;
      }
    }
  }
</style>
